package com.invengo.library_rfid.analyze.utils.uhf.formatHelp;

import java.util.Arrays;

public class CBitClassFromLow implements Comparable {
    private int _cur_byte_index;
    private int _empty_bits_in_cur_byte;
    private byte[] _bytes_value;
    private int _byte_length = 12;

    public int getWrited_byte_length() {
        return _cur_byte_index;
    }

    public byte[] getBytes_value() {
        return _bytes_value;
    }

    public int getByte_length() {
        return _byte_length;
    }

    public CBitClassFromLow() {
        _byte_length = 12;
        _cur_byte_index = 0;
        _empty_bits_in_cur_byte = 0;
        _bytes_value = new byte[12];
    }

    public CBitClassFromLow(int nLength) {
        _byte_length = nLength;
        _cur_byte_index = 0;
        _empty_bits_in_cur_byte = 0;
        _bytes_value = new byte[nLength];
    }

    public CBitClassFromLow(byte[] byData) {
        _byte_length = byData.length;
        _cur_byte_index = _byte_length;
        _empty_bits_in_cur_byte = 0;
        _bytes_value = Arrays.copyOf(byData, byData.length);
    }

    public int addBits(String szValue) {
        for (int i = 0; i < szValue.length(); i++) {
            _bytes_value[_cur_byte_index] += (byte) szValue.charAt(i);
            _cur_byte_index++;
        }
        return _cur_byte_index;
    }

    public int addBitsWithChinese(String szValue) {
        for (int i = 0; i < szValue.length(); i++) {
            byte[] tempBytes = szValue.substring(i, i + 1).getBytes();
            for (byte tempByte : tempBytes) {
                _bytes_value[_cur_byte_index] += tempByte;
                _cur_byte_index++;
            }
        }
        return _cur_byte_index;
    }

    public int addBits(long lvalue, int bits_space_count) {
        int used_bitslength_for_lvalue = 0;
        if (_empty_bits_in_cur_byte > 0) {
            if (_empty_bits_in_cur_byte >= bits_space_count) {
                _bytes_value[_cur_byte_index] += (byte) (lvalue << (8 - _empty_bits_in_cur_byte));
                _empty_bits_in_cur_byte -= bits_space_count;
                if (_empty_bits_in_cur_byte == 0) {
                    _cur_byte_index++;
                }
                return _cur_byte_index;
            }
            _bytes_value[_cur_byte_index] += (byte) (lvalue << (8 - _empty_bits_in_cur_byte));
            lvalue = lvalue >> _empty_bits_in_cur_byte;
            used_bitslength_for_lvalue = _empty_bits_in_cur_byte;
            _empty_bits_in_cur_byte = 0;
            _cur_byte_index++;
        }
        while (bits_space_count - used_bitslength_for_lvalue > 8) {
            _bytes_value[_cur_byte_index] += (byte) lvalue;
            lvalue = lvalue >> 8;
            used_bitslength_for_lvalue += 8;
            _cur_byte_index++;
        }
        if (bits_space_count - used_bitslength_for_lvalue > 0) {
            _bytes_value[_cur_byte_index] += (byte) lvalue;
            _empty_bits_in_cur_byte = 8 - (bits_space_count - used_bitslength_for_lvalue);
            if (_empty_bits_in_cur_byte == 0) {
                _cur_byte_index++;
            }
        }
        return _cur_byte_index;
    }

    public int addBytes(byte[] bytes) {
        if (_empty_bits_in_cur_byte == 0) {
            for (int i = 0; i < bytes.length; i++) {
                _bytes_value[_cur_byte_index] += bytes[i];
                _cur_byte_index++;
                if (_cur_byte_index == _bytes_value.length) {
                    break;
                }
            }
            return _cur_byte_index;
        } else {
            for (int i = 0; i < bytes.length; i++) {
                _bytes_value[_cur_byte_index] += (byte) (bytes[i] << (8 - _empty_bits_in_cur_byte));
                _cur_byte_index++;
                if (_cur_byte_index == _bytes_value.length) {
                    break;
                }
                _bytes_value[_cur_byte_index] += (byte) (bytes[i] >> _empty_bits_in_cur_byte);
            }
            return _cur_byte_index;
        }
    }

    public long getValue(int start_bits_position, int bits_length) {
        int geted_bit_count = 0;
        int pre_byte_position = start_bits_position % 8;
        int start_byte_index = start_bits_position / 8;
        long nResult = 0;
        if (pre_byte_position > 0) {
            if (bits_length <= 8 - pre_byte_position) {
                geted_bit_count = bits_length;
                byte bStep1 = (byte) (_bytes_value[start_byte_index] >> pre_byte_position);
                byte temp = (byte) (Math.pow(2, (double) bits_length) - 1);
                nResult = (long) (bStep1 & temp);
                return nResult;
            } else {
                geted_bit_count = 8 - pre_byte_position;
                byte bStep1 = (byte) (_bytes_value[start_byte_index] >> pre_byte_position);
                byte temp = (byte) (Math.pow(2, (double) (8 - pre_byte_position)) - 1);
                nResult = (long) (bStep1 & temp);
            }
            start_byte_index++;
        }
        while (bits_length - geted_bit_count >= 8) {
            nResult += (long) (((long) _bytes_value[start_byte_index]) << geted_bit_count);
            geted_bit_count += 8;
            start_byte_index++;
        }
        if (bits_length - geted_bit_count > 0) {
            byte temp = (byte) (Math.pow(2, (double) (bits_length - geted_bit_count)) - 1);
            nResult += (long) (((long) (_bytes_value[start_byte_index] & temp)) << geted_bit_count);
        }
        return nResult;
    }

    public int getBytes(byte[] byArray) {
        System.arraycopy(_bytes_value, 0, byArray, 0, _cur_byte_index);
        return _cur_byte_index;
    }

    @Override
    public String toString() {
        StringBuilder szTemp = new StringBuilder();
        for (byte b : _bytes_value) {
            szTemp.append(String.format("%02X", b));
        }
        return szTemp.toString();
    }

    @Override
    public int compareTo(Object obj) {
        if (!(obj instanceof CBitClassFromLow) || obj == null) {
            return -1;
        }
        CBitClassFromLow other = (CBitClassFromLow) obj;
        return toString().compareTo(obj.toString());
    }
}


